import {
  ExceptionFilter,
  Catch,
  ArgumentsHost,
  HttpException,
  HttpStatus,
} from '@nestjs/common';
import { Request, Response } from 'express';
import { R } from '../response/response.util';

/**
 * HTTP异常过滤器
 * 用于捕获并处理应用程序中抛出的异常，将其转换为标准的响应格式
 */
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  /**
   * 捕获并处理异常
   * @param exception 异常对象
   * @param host 参数主机
   */
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();

    // 获取异常响应
    const exceptionResponse = exception.getResponse();
    let message = exception.message;

    // 如果异常响应是对象且包含message字段，则使用该message
    if (
      typeof exceptionResponse === 'object' &&
      'message' in exceptionResponse
    ) {
      message = Array.isArray(exceptionResponse['message'])
        ? (exceptionResponse['message'] as string[]).join(', ')
        : (exceptionResponse['message'] as string);
    }

    // 使用R工具类创建错误响应
    const errorResponse = R.error(status, message);

    // 发送响应
    response.status(status).json(errorResponse);
  }
}

/**
 * 全局异常过滤器
 * 用于捕获并处理应用程序中抛出的所有异常，将其转换为标准的响应格式
 */
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  /**
   * 捕获并处理异常
   * @param exception 异常对象
   * @param host 参数主机
   */
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    // 如果是HTTP异常，则使用其状态码，否则使用500
    const status =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;

    // 获取错误消息
    let message = 'Internal server error';
    if (exception instanceof HttpException) {
      const exceptionResponse = exception.getResponse();
      if (
        typeof exceptionResponse === 'object' &&
        'message' in exceptionResponse
      ) {
        message = Array.isArray(exceptionResponse['message'])
          ? (exceptionResponse['message'] as string[]).join(', ')
          : (exceptionResponse['message'] as string);
      } else {
        message = exception.message;
      }
    } else if (exception instanceof Error) {
      message = exception.message;
    }

    // 使用R工具类创建错误响应
    const errorResponse = R.error(status, message);

    // 发送响应
    response.status(status).json(errorResponse);
  }
}
